import { get } from '@ugeez/frontend-commons/lib/service';
import { ImageRawData, RemoteFile, SourceData, UploadTicket } from '@ugeez/frontend-commons/lib/types';
import { convertImageRawDataToFile, parseFileExt, parseFilename } from '@ugeez/frontend-commons/lib/utils';
import axios from 'axios';

import { randomString } from '@ugeez/frontend-commons/lib/utils';
import { getGlobalConfig } from '@ugeez/frontend-commons';

export type Captcha = {
    sessId: string;
    url: string;
};

export const refreshCaptcha = async (): Promise<Captcha> => {
    const sessId = randomString(12);
    const { setting } = getGlobalConfig();
    let fullUrl: string = setting.apiGateway;
    if (!fullUrl.endsWith('/')) {
        fullUrl = fullUrl + '/';
    }
    fullUrl = fullUrl + 'utils/captcha?sessId=' + sessId;
    return {
        sessId,
        url: fullUrl,
    };
};

export const generateUploadToken = async (ext: string, folder = '', isPrivate: boolean = false): Promise<UploadTicket> => {
    const { accessId, key, token, policy, action } = await get('/utils/获取上传token接口', {
        ext,
        folder,
        isPrivate,
    });
    const filename = parseFilename(key);
    return {
        accessKey: accessId,
        action: action,
        key,
        token: token,
        policy,
        filename
    };
};

export const getOSSObjectInfo = async (key: string, isPrivate: boolean): Promise<RemoteFile> => {
    const res = await get('/utils/获取OSS文件信息', {
        key,
        isPrivate
    });
    return {
        key: res.key,
        filename: res.filename,
        ext: parseFileExt(res.key),
        size: res.size,
        md5: res.md5,
        createTime: res.createTime,
    };
};

export const getPrivateOSSObjectUrl = async (src: string | RemoteFile): Promise<string> => {
    const key: string = typeof src === 'object' ? src.key : src;
    const args: SourceData = {
        key,
    };
    if (typeof src === 'object' && src.filename) {
        args.saveAs = src.filename;
    }
    const { url } = await get('/utils/获取私有OSS文件信息', args);
    return url;
};

export const uploadImageFile = (image: ImageRawData, filename?: string, folder = '', isPrivate: boolean = false): Promise<RemoteFile> => {
    const file = convertImageRawDataToFile(image, filename);
    return uploadFile(file, file.name, folder, isPrivate);
};

export const uploadFile = async (file: File | Blob, originalFilename: string, folder = '', isPrivate: boolean = false, buildConfig?: (config: Record<string, any>) => Record<string, any>): Promise<RemoteFile> => {
    const ext = parseFileExt(originalFilename);
    const { accessKey, action, token, key, filename, policy } = await generateUploadToken(ext, folder, isPrivate);

    const param = new FormData(); // 创建form对象
    param.append('key', key); // 通过append向form对象添加数据
    param.append('token', token);
    param.append('file', file); // 通过append向form对象添加数据
    let config: Record<string, any> = {
        crossdomain: true,
        headers: { 'Content-Type': 'multipart/form-data' }
    };
    if (buildConfig) {
        config = buildConfig(config);
    }
    // 添加请求头
    await axios.post(action, param, config);

    const remoteFile: RemoteFile = await getOSSObjectInfo(key, isPrivate);
    remoteFile.filename = originalFilename;
    return remoteFile;
};